package com.study.thread.lockSupport;

import java.util.concurrent.locks.LockSupport;

/*
    LockSupport：是一个挂起和唤醒线程的工具类，主要使用的是Unsafe来实现的，一些juc下的锁都是用LockSupport来挂起和唤醒线程的，LockSupport会与每个使用它的线程关联一个许可证
        默认情况下调用LockSupport类的方法是不持有许可证的，因此调用LockSupport的park方法的线程会被禁止参与线程的调度，也就是会被挂起。
            park()：如果调用的线程持有了与LockSupport关联的许可证（如果先使用unpark就会有关联许可证），则调用park会立马返回（也就是不会阻塞），否则会被禁止参与线程调度，也就是被阻塞挂起。
                以下情况会被返回：
                    1、当其它线程调用unpark(Thread thread)方法，并且将当前阻塞线程作为参数时，调用park方法而被阻塞的线程就会返回。
                    2、其它线程调用了阻塞线程的interrupt方法，但是不会抛出InterruptedException异常
                    3、线程被虚假唤醒，建议也使用while判断进行挂起线程
            unpark(Thread thread)：当线程调用unpark时，如果参数thread线程没有持有thread与LockSupport的许可证，则让thread持有，如果thread之前因调用
                 park()而被挂起，则调用unpark(thread)后，该线程被唤醒，如果thread没有之前调用park，则先调用unpark关联许后，在调用park会立刻返回，不会挂起！
            park(Object blocker)：和park功能一样，多一个参数尽量是调用线程的实例，主要用来在线程分析的时候区分是哪个类里调用的park！
            parkNanos(long nanos)：和park功能一样，但是指定一个超时时间，当超时时间到了会唤醒线程
*/
public class LockSupportDemo1 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("begin park");

        // 许可证关联时在调用park时会直接返回。
        // 关联许可证
      /*  LockSupport.unpark(Thread.currentThread());
        // 挂起线程
        LockSupport.park();*/

      /*  // 使用普通的park和unpark来挂起和唤醒
        Thread t1 = new Thread(() -> {
            System.out.println("线程开始运行");
            while (!Thread.currentThread().isInterrupted()) {
                LockSupport.park(new LockSupportDemo1()); //挂起线程
            }

            System.out.println("线程结束运行");
        });
        t1.start();
        Thread.sleep(1000);
        LockSupport.unpark(t1); // 唤醒线程，可以注释掉看阻塞效果 // 因为里面调用的while判断当前线程是否中断所以会一直挂起
//        t1.interrupt(); // 使用线程中断唤醒线程，不会抛出中断异常*/

        // 使用parkNanos(long nanos)来通过时间挂起线程
        Thread t1 = new Thread(() -> {
            System.out.println("线程开始运行");
            LockSupport.parkNanos(new LockSupportDemo1(),800000000); //挂起线程,超时时间过了就唤醒线程
            System.out.println("线程结束运行");
        });
        t1.start();

        System.out.println("end park");
    }


}
